package com.njtoyo.taxi.admin.service.business.driver.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.excel.EasyExcel;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.njtoyo.taxi.admin.library.common.OperationRecordHelper;
import com.njtoyo.taxi.admin.library.sms.YunpianSmsClient;
import com.njtoyo.taxi.admin.library.taxi_service.TaxiService;
import com.njtoyo.taxi.admin.library.traffic_info.Conditions;
import com.njtoyo.taxi.admin.library.traffic_info.Param;
import com.njtoyo.taxi.admin.library.traffic_info.TrafficInfoQueryClient;
import com.njtoyo.taxi.admin.logic.driver.DriverAuditLogic;
import com.njtoyo.taxi.admin.mapper.master.entity.*;
import com.njtoyo.taxi.admin.mapper.master.enums.*;
import com.njtoyo.taxi.admin.mapper.master.fields.operation_rule.DriverRegistrationInfoRejectReason;
import com.njtoyo.taxi.admin.mapper.master.mapper.*;
import com.njtoyo.taxi.admin.rest.export.driver.DriverRegistrationInfoExportPresenter;
import com.njtoyo.taxi.admin.rest.presenter.business.driver.DriverAuditInfoDetailsPresenter;
import com.njtoyo.taxi.admin.rest.presenter.business.driver.DriverAuditPagePresenter;
import com.njtoyo.taxi.admin.rest.presenter.platfrom.AdminUserIdentityPresenter;
import com.njtoyo.taxi.admin.rest.wrapper.business.driver.*;
import com.njtoyo.taxi.admin.rest.wrapper.business.driver.system_message.DriverAuditSendMsgWrapper;
import com.njtoyo.taxi.admin.service.business.driver.DriverRegistrationInfoService;
import com.njtoyo.taxi.entity.backend.AdminUser;
import com.taxi.entity.common.RestResult;
import com.taxi.entity.common.ResultEnum;
import com.yunpian.sdk.YunpianException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.mail.MessagingException;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;

import static com.yunpian.sdk.util.HttpUtil.post;
import static java.util.stream.Collectors.toList;
import static org.springframework.util.ObjectUtils.isEmpty;

@Slf4j
@Service
public class DriverRegistrationInfoServiceImpl implements DriverRegistrationInfoService {

    @Autowired
    private DriverAuditInfoMapper driverAuditInfoMapper;

    @Autowired
    private GeoDriverRegionMapper geoDriverRegionMapper;

    @Autowired
    private CompanyMapper companyMapper;

    @Autowired
    private DriverMapper driverMapper;

    @Autowired
    private TaxiMapper taxiMapper;

    @Autowired
    private DriverExtraInformationMapper driverExtraInformationMapper;

    @Autowired
    private OperationRecordHelper operationRecordHelper;

    @Autowired
    private YunpianSmsClient yunpianSmsClient;

    @Autowired
    private GeoDriverRegionAreaMapper geoDriverRegionAreaMapper;

    @Autowired
    private GeoAreaMapper geoAreaMapper;

    @Autowired
    private MemberMapper memberMapper;

    @Autowired
    private DriverCustomMessageMapper driverCustomMessageMapper;

    @Autowired
    private DriverAuditLogic driverAuditLogic;

    @Autowired
    private TaxiService taxiService;

    @Autowired
    private RecommendationRelationshipMapper recommendationRelationshipMapper;

    //短信链接url
    @Value("${config.taxiDriverRegistrationLink}")
    private String url;

    /**
     * 司机自主注册审核列表
     *
     * @param adminUser
     * @param wrapper
     * @return
     */
    @Override
    public RestResult<Page<DriverAuditPagePresenter>> getPage(AdminUser adminUser,
                                                              DriverAuditQueryWrapper wrapper) {
        AdminUserIdentityPresenter identity = (AdminUserIdentityPresenter) adminUser.getIdentity();
        switch (adminUser.getAccountType()) {
            case company:
                wrapper.setCompanyIds(identity.getCompanyIds());
                break;
            case canton:
                wrapper.setDriverRegionIds(identity.getDriverRegionIds());
                break;
        }
        Page<DriverAuditPagePresenter> list =
                driverAuditInfoMapper.selectDriverRegistrationInfo(wrapper);
        List<Long> ids = list.getRecords().stream()
                .map(DriverAuditPagePresenter::getId)
                .collect(toList());
        List<Long> driverRegionIds = list.getRecords().stream()
                .map(DriverAuditPagePresenter::getDriverRegionId)
                .collect(toList());
        List<Long> companyIds = list.getRecords().stream()
                .map(DriverAuditPagePresenter::getCompanyId)
                .collect(toList());
        //验证是否存在数据
        if (isEmpty(ids)) {
            return RestResult.success(list);
        }
        //驳回原因转换格式
        //运营区名称
        QueryWrapper<GeoDriverRegion> driverRegionQueryWrapper = new QueryWrapper<>();
        driverRegionQueryWrapper.select("id", "name");
        driverRegionQueryWrapper.in("id", driverRegionIds);
        List<Map<String, Object>> maps = geoDriverRegionMapper.selectMaps(driverRegionQueryWrapper);
        //公司名称
        QueryWrapper<Company> companyQueryWrapper = new QueryWrapper<>();
        companyQueryWrapper.select("id", "name");
        companyQueryWrapper.in("id", companyIds);
        List<Map<String, Object>> companyMaps = companyMapper.selectMaps(companyQueryWrapper);

        list.getRecords().forEach(e -> {
            Long driverRegionId = e.getDriverRegionId();
            Long companyId = e.getCompanyId();
            //行政区信息
            maps.stream().filter(c -> c.get("id").equals(driverRegionId)).map(c -> String.valueOf(c.get("name"))).forEach(e::setDriverRegionName);
            //公司名称
            companyMaps.stream().filter(c -> c.get("id").equals(companyId)).map(c -> String.valueOf(c.get("name"))).forEach(e::setCompanyName);
        });
        return RestResult.success(list);
    }

    /**
     * 司机自主注册审核详情
     *
     * @param id
     * @return
     */
    @Override
    public RestResult<DriverAuditInfoDetailsPresenter> details(Long id) {
        DriverAuditInfo driverRegistrationInfo =
                driverAuditInfoMapper.selectById(id);
        if (isEmpty(driverRegistrationInfo)) {
            return RestResult.build(ResultEnum.NOT_FOUND);
        }
        DriverAuditInfoDetailsPresenter driverAuditInfoDetailsPresenter
                = new DriverAuditInfoDetailsPresenter();
        BeanUtils.copyProperties(driverRegistrationInfo, driverAuditInfoDetailsPresenter);
        Long driverRegionId = driverAuditInfoDetailsPresenter.getDriverRegionId();
        Long companyId = driverAuditInfoDetailsPresenter.getCompanyId();
        //运营区名称
        if (driverRegionId != null) {
            GeoDriverRegion geoDriverRegion = geoDriverRegionMapper.selectById(driverRegionId);
            if (!isEmpty(geoDriverRegion)) {
                driverAuditInfoDetailsPresenter.setDriverRegionName(geoDriverRegion.getName());
            }
        }
        if (companyId != null) {
            Company company = companyMapper.selectById(companyId);
            if (!isEmpty(company)) {
                driverAuditInfoDetailsPresenter.setCompanyName(company.getName());
            }
        }

        // 获取日志
        driverAuditInfoDetailsPresenter.setAuditLogList(driverAuditLogic.selectByAuditId(id));

        return RestResult.success(driverAuditInfoDetailsPresenter);
    }

    /**
     * 司机自主注册审核修改信息
     *
     * @param id
     * @param wrapper
     * @return
     */
    @Override
    public RestResult update(Long id, DriverRegistrationInfoUpdateWrapper wrapper) {
        DriverAuditInfo driverRegistrationInfo =
                driverAuditInfoMapper.selectById(id);
        if (isEmpty(driverRegistrationInfo)) {
            return RestResult.build(ResultEnum.NOT_FOUND);
        }
        String identityNumber = wrapper.getIdentityNumber();
        String driverLicenceNumber = wrapper.getDriverLicenceNumber();
        String roadTransportNumber = wrapper.getRoadTransportNumber();
        //附加表身份证唯一 ,附加表驾驶证唯一,附加表道路运输证唯一
        QueryWrapper<DriverExtraInformation> driverExtraInformationQueryWrapper = new QueryWrapper<>();
        if (Objects.nonNull(identityNumber) || Objects.nonNull(driverLicenceNumber) || Objects.nonNull(roadTransportNumber)) {
            driverExtraInformationQueryWrapper
                    .eq("identity_number", identityNumber)
                    .or()
                    .eq("driver_licence_number", driverLicenceNumber)
                    .or()
                    .eq("road_transport_number", roadTransportNumber);
            List<DriverExtraInformation> driverExtraInformations = driverExtraInformationMapper.selectList(driverExtraInformationQueryWrapper);
            if (!isEmpty(driverExtraInformations)) {
                return RestResult.failed("证件已经存在");
            }
        }

        //修改司机自主注册审信息
        new LambdaUpdateChainWrapper<>(driverAuditInfoMapper)
                .eq(DriverAuditInfo::getId, id)
                .set(DriverAuditInfo::getName, wrapper.getName())
                .set(DriverAuditInfo::getDriverRegionId, wrapper.getDriverRegionId())
                .set(DriverAuditInfo::getCompanyId, wrapper.getCompanyId())
                .set(DriverAuditInfo::getPlateNumber, wrapper.getPlateNumber())
                .set(DriverAuditInfo::getDeviceId, wrapper.getDeviceId())
                .set(DriverAuditInfo::getServiceNumber, wrapper.getServiceNumber())
                .set(DriverAuditInfo::getIdentityNumber, wrapper.getIdentityNumber())
                .set(DriverAuditInfo::getDriverLicenceNumber, wrapper.getDriverLicenceNumber())
                .set(DriverAuditInfo::getUpdatedAt, new Date())
                .set(DriverAuditInfo::getEngineNumber, wrapper.getEngineNumber())
                .set(DriverAuditInfo::getRoadTransportNumber, wrapper.getRoadTransportNumber())
                .set(DriverAuditInfo::getQualificationCertificateExpiringTimestamp, wrapper.getQualificationCertificateExpiringTimestamp())
                .set(DriverAuditInfo::getVehicleLicenceExpiringTimestamp, wrapper.getVehicleLicenceExpiringTimestamp())
                .update();

        //操作日志信息
        operationRecordHelper.addBusinessLog(String.format("修改了司机自主注册审核 [%d] 的信息", id));
        return RestResult.success();
    }

    /**
     * 司机自主注册审核信息
     *
     * @param id
     * @param wrapper
     * @return
     */
    @Override
    @DSTransactional
    public RestResult examine(AdminUser adminUser, Long id, DriverRegistrationInfoExamineWrapper wrapper) throws UnsupportedEncodingException {
        DriverAuditInfo driverRegistrationInfo =
                driverAuditInfoMapper.selectById(id);
        if (isEmpty(driverRegistrationInfo)) {
            return RestResult.build(ResultEnum.NOT_FOUND);
        }
        DriverRegistrationInfoSate state1 = driverRegistrationInfo.getState();
        if (!DriverRegistrationInfoSate.under_review.equals(state1)) {
            return RestResult.failed("已经审核过了");
        }

        String name = driverRegistrationInfo.getName();
        Long driverRegionId = driverRegistrationInfo.getDriverRegionId();
        String mobileNumber = driverRegistrationInfo.getMobileNumber();
        Long companyId = driverRegistrationInfo.getCompanyId();
        String plateNumber = driverRegistrationInfo.getPlateNumber();
        String identityNumber = driverRegistrationInfo.getIdentityNumber();
        String driverLicenceNumber = driverRegistrationInfo.getDriverLicenceNumber();

        String vehicleLicenceNumber = driverRegistrationInfo.getVehicleLicenceNumber();
        String qualificationCertificateNumber = driverRegistrationInfo.getQualificationCertificateNumber();
        //行驶证从业资格证暂不使用改为车辆发动机号和道路运输证号
        String engineNumber = driverRegistrationInfo.getEngineNumber();
        String roadTransportNumber = driverRegistrationInfo.getRoadTransportNumber();

        //信息不能为空
        if (StringUtils.isEmpty(mobileNumber) || StringUtils.isEmpty(name) || StringUtils.isEmpty(plateNumber)
                || StringUtils.isEmpty(companyId) || StringUtils.isEmpty(driverRegionId) || StringUtils.isEmpty(identityNumber)) {
            return RestResult.build(ResultEnum.PARAMS_ERROR);
        }
        //cantonId取公司的
        Long locateCityId = driverRegionId;
        QueryWrapper<Company> companyQueryWrapper = new QueryWrapper<>();
        companyQueryWrapper.eq("id", companyId);
        companyQueryWrapper.select("id", "canton_id", "city_id");
        Company company = companyMapper.selectOne(companyQueryWrapper);
        if (!isEmpty(company)) {
            if (!isEmpty(company.getCityId())) {
                locateCityId = company.getCityId();
            }

        }

        //司机的城市ID
        QueryWrapper<GeoDriverRegionArea> driverRegionAreaQueryWrapper = new QueryWrapper<>();
        driverRegionAreaQueryWrapper.eq("driver_region_id", driverRegionId);
        driverRegionAreaQueryWrapper.orderByDesc("driver_region_id");
        List<GeoDriverRegionArea> geoDriverRegionAreas = geoDriverRegionAreaMapper.selectList(driverRegionAreaQueryWrapper);
        if (!isEmpty(geoDriverRegionAreas)) {
            Long areaId = geoDriverRegionAreas.get(0).getAreaId();
            GeoArea geoArea = geoAreaMapper.selectById(areaId);
            if (geoArea != null) {
                Long cityId = geoArea.getCityId();
                if (!isEmpty(cityId)) {
                    locateCityId = cityId;
                }
            }
        }
        DriverRegistrationInfoSate state = wrapper.getState();

        DriverAuditLog auditLog = new DriverAuditLog();
        auditLog.setDriverAuditId(id);
        auditLog.setAdminId(adminUser.getId());
        auditLog.setState(state);

        switch (state) {
            case adopt:
                //审核通过,注册司机
                new LambdaUpdateChainWrapper<>(driverAuditInfoMapper)
                        .eq(DriverAuditInfo::getId, id)
                        .set(DriverAuditInfo::getState, wrapper.getState())
                        .set(DriverAuditInfo::getUpdatedAt, new Date())
                        .update();

                //车辆信息
                QueryWrapper<Taxi> taxiQueryWrapper = new QueryWrapper<>();
                taxiQueryWrapper.eq("plate_number", plateNumber);
                Taxi taxi = taxiMapper.selectOne(taxiQueryWrapper);
                Long taxiId = null;

                //注册车辆,有绑定,没有注册车辆
                if (isEmpty(taxi)) {
                    Taxi newTaxi = new Taxi();
                    newTaxi.setPlateNumber(plateNumber);
                    newTaxi.setCompanyId(companyId);
                    newTaxi.setIsScrapped(false);
                    newTaxi.setIsAvailable(true);
                    newTaxi.setSerialNumber(Objects.isNull(engineNumber) ? plateNumber : engineNumber);
                    taxiMapper.insert(newTaxi);
                    taxiId = newTaxi.getId();
                } else {
                    taxiId = taxi.getId();
                }
                //手机号后6位做密码
                String mobile = mobileNumber.substring(5);
                String md5 = DigestUtil.md5Hex(mobile);
                // 添加司机信息
                Driver driver = new Driver();
                driver.setName(name)
                        .setMobileNumber(mobileNumber)
                        .setPassword(md5)
                        .setAvatarUrl("https://store.jjtoyo.com/driver/driver-head.png")
                        .setLocateCityId(locateCityId)
                        .setDriverRegionId(driverRegionId)
                        .setCantonId(company.getCantonId())
                        .setIsActive(true)
                        .setTaxiId(taxiId);
                driverMapper.insert(driver);
                log.info("插入司机信息 {}", driver);

                // 添加会员信息
                Member member = new Member();
                member.setCategory(MemberCategory.driver)
                        .setRefId(driver.getId());
                memberMapper.insert(member);
                log.info("插入会员信息 {}", member);

                // 司机消息
                DriverCustomMessage message = new DriverCustomMessage();
                message.setDriverId(driver.getId())
                        .setContent("欢迎使用巡网融合出行平台，优质派单、安全出行。")
                        .setIsPlainText(true)
                        .setLinkCategory(DriverCustomMessageLinkCategory.self)
                        .setEventCategory(DriverCustomMessageEventCategory.system)
                        .setIsRead(false);
                driverCustomMessageMapper.insert(message);
                log.info("插入司机消息 {}", message);

                //回填审核表 driver id
                new LambdaUpdateChainWrapper<>(driverAuditInfoMapper)
                        .eq(DriverAuditInfo::getId, id)
                        .set(DriverAuditInfo::getDriverId, driver.getId())
                        .set(DriverAuditInfo::getUpdatedAt, new Date())
                        .update();

                //司机扩展信息
                DriverExtraInformation driverExtraInformation = new DriverExtraInformation();
                driverExtraInformation.setDriverId(driver.getId());
                driverExtraInformation.setDriverLicenceNumber(driverLicenceNumber);
                driverExtraInformation.setIdentityNumber(identityNumber);
                driverExtraInformation.setVehicleLicenceNumber(vehicleLicenceNumber);
                driverExtraInformation.setQualificationCertificateNumber(qualificationCertificateNumber);
                driverExtraInformation.setEngineNumber(driverRegistrationInfo.getEngineNumber());
                driverExtraInformation.setRoadTransportNumber(driverRegistrationInfo.getRoadTransportNumber());
                driverExtraInformation.setVehicleLicenceExpiringTimestamp(driverRegistrationInfo.getVehicleLicenceExpiringTimestamp());
                driverExtraInformation.setQualificationCertificateExpiringTimestamp(driverRegistrationInfo.getQualificationCertificateExpiringTimestamp());

                DriverExtraInformation states = driverAuditLogic.getStateForAdopt(driverRegistrationInfo);

                driverExtraInformation.setNormalState(states.getNormalState());
                driverExtraInformation.setUpdateState(states.getUpdateState());
                driverExtraInformation.setOverdueState(states.getOverdueState());

                driverExtraInformationMapper.insert(driverExtraInformation);
                log.info("插入司机扩展信息 {}", message);

                // 校验是否存在推荐关系
                LambdaQueryWrapper<RecommendationRelationship> recommendWrapper = new LambdaQueryWrapper<>();
                recommendWrapper.eq(RecommendationRelationship::getRefId, id)
                        .eq(RecommendationRelationship::getRecommendationPlatform, RecommendationRelationPlatform.h5)
                        .eq(RecommendationRelationship::getFromCategory, RecommendationFromCategoryPlatform.driver)
                        .eq(RecommendationRelationship::getToCategory, RecommendationFromCategoryPlatform.driver);

                RecommendationRelationship recommend = recommendationRelationshipMapper.selectOne(recommendWrapper);

                // 存在则更新
                if (Objects.nonNull(recommend)) {
                    RecommendationRelationship updateRecommend = new RecommendationRelationship();
                    updateRecommend.setId(recommend.getId());
                    updateRecommend.setToId(driver.getId());
                    updateRecommend.setActivePlatform(RecommendationRelationPlatform.h5);
                    updateRecommend.setActivatedAt(new Date());
                    updateRecommend.setIsActivated(true);
                    updateRecommend.setIsValid(true);

                    recommendationRelationshipMapper.updateById(updateRecommend);
                    log.info("更新司机推荐司机关系 {}", updateRecommend);
                }

                try {
                    sendMessage(mobileNumber, DriverRegistrationInfoSate.adopt);
                } catch (MessagingException | YunpianException e) {
                    e.printStackTrace();
                }
                break;
            case refuse:
                //拒绝
                new LambdaUpdateChainWrapper<>(driverAuditInfoMapper)
                        .eq(DriverAuditInfo::getId, id)
                        .set(DriverAuditInfo::getState, DriverRegistrationInfoSate.refuse)
                        .set(DriverAuditInfo::getUpdatedAt, new Date())
                        .update();
                //发送短信告知审核结果 ,有问题找客服
                try {
                    sendMessage(mobileNumber, DriverRegistrationInfoSate.refuse);
                } catch (MessagingException | YunpianException e) {
                    e.printStackTrace();
                }
                break;
            case abolish:
                //TODO 废除暂时不写,待定
                new LambdaUpdateChainWrapper<>(driverAuditInfoMapper)
                        .eq(DriverAuditInfo::getId, id)
                        .set(DriverAuditInfo::getState, DriverRegistrationInfoSate.abolish)
                        .set(DriverAuditInfo::getUpdatedAt, new Date())
                        .update();
                //过了有效期就废除
                break;
        }

        driverAuditLogic.saveLog(auditLog);

        //操作日志信息
        operationRecordHelper.addBusinessLog(String.format("审核了司机自主注册审核 [%d] 的信息,状态为 %s", id, wrapper.getState()));
        return RestResult.success();
    }


    /**
     * 驳回审核信息
     *
     * @param id
     * @param wrapper
     * @return
     */
    @Override
    public RestResult reject(AdminUser adminUser, Long id, DriverRegistrationInfoExamineWrapper wrapper) throws UnsupportedEncodingException {
        DriverAuditInfo driverRegistrationInfo =
                driverAuditInfoMapper.selectById(id);
        if (isEmpty(driverRegistrationInfo)) {
            return RestResult.build(ResultEnum.NOT_FOUND);
        }
        DriverRegistrationInfoSate state = driverRegistrationInfo.getState();
        if (!DriverRegistrationInfoSate.under_review.equals(state)) {
            return RestResult.failed("已经审核过了");
        }

        String mobileNumber = driverRegistrationInfo.getMobileNumber();
        //驳回必须写具体原因 json
        DriverRegistrationInfoRejectReason rejectReason =
                wrapper.getRejectReason();
        if (isEmpty(rejectReason)) {
            return RestResult.build(ResultEnum.NOT_FOUND);
        }

        ArrayList<Object> list = new ArrayList<>();
        list.add(rejectReason);

        new LambdaUpdateChainWrapper<>(driverAuditInfoMapper)
                .eq(DriverAuditInfo::getId, id)
                .set(DriverAuditInfo::getState, DriverRegistrationInfoSate.noadopt)
                .set(DriverAuditInfo::getRejectReason, JSONUtil.toJsonStr(list))
                .set(DriverAuditInfo::getUpdatedAt, new Date())
                .update();
        //驳回,短信给客服联系方式
        try {
            //测试
            sendMessage(mobileNumber, DriverRegistrationInfoSate.noadopt);
        } catch (MessagingException | YunpianException e) {
            e.printStackTrace();
        }

        DriverAuditLog auditLog = new DriverAuditLog();
        auditLog.setDriverAuditId(id);
        auditLog.setAdminId(adminUser.getId());
        auditLog.setState(DriverRegistrationInfoSate.noadopt);
        auditLog.setNote(JSONUtil.toJsonStr(list));

        driverAuditLogic.saveLog(auditLog);

        operationRecordHelper.addBusinessLog(String.format("驳回了司机自主注册审核 [%d] 的信息", id));
        return RestResult.success();
    }

    /**
     * 校验审核信息
     *
     * @param id
     */
    @Override
    public RestResult check(Long id) {
        //校验审核的信息
        DriverAuditInfo driverRegistrationInfo =
                driverAuditInfoMapper.selectById(id);
        if (isEmpty(driverRegistrationInfo)) {
            return RestResult.build(ResultEnum.NOT_FOUND);
        }
        String name = driverRegistrationInfo.getName();
        String identityNumber = driverRegistrationInfo.getIdentityNumber();
        Long driverRegionId = driverRegistrationInfo.getDriverRegionId();
        String adCode = "210000";
        //查询司机运营区的地区
        //会员信息
        QueryWrapper<GeoDriverRegionArea> driverRegionAreaQueryWrapper = new QueryWrapper<>();
        driverRegionAreaQueryWrapper.select("area_id");
        driverRegionAreaQueryWrapper.in("driver_region_id", driverRegionId);
        List<GeoDriverRegionArea> geoDriverRegionAreas = geoDriverRegionAreaMapper.selectList(driverRegionAreaQueryWrapper);
        if (!isEmpty(geoDriverRegionAreas)) {
            GeoDriverRegionArea geoDriverRegionArea = geoDriverRegionAreas.get(0);
            GeoArea geoArea = geoAreaMapper.selectById(geoDriverRegionArea.getAreaId());
            String areaAdCode = geoArea.getAdCode();
            adCode = areaAdCode.substring(0, 2) + "0000";
        }

        Conditions conditions = new Conditions();
        //CertificateCode 证件
        //ProvinceCode 省号
        conditions.add("StaffName", name)
                .add("CertificateCode", identityNumber)
                .add("ProvinceCode", adCode);

        TrafficInfoQueryClient client = new TrafficInfoQueryClient();
        client.setKey("e35264546f5f4de1b2123ea079e93ded").setSign("jtbdlyzry")
                .setAccess_token("4bdcd791b46f0b0d61629876ddb35947")
                .setParam(new Param("133I0O2984010388", conditions))
                .setReferer("http://app.gjzwfw.gov.cn/jmopen/webapp/html5/jtbdlyzry/index.html");

        return RestResult.success(client.send());
    }

    /**
     * 发送短信模板
     *
     * @param
     * @throws MessagingException
     */
    @Async
    public void sendMessage(String mobileNumber, DriverRegistrationInfoSate state) throws MessagingException, UnsupportedEncodingException, YunpianException {
        log.info("正在发送发送短信 {}", mobileNumber);
        switch (state) {
            case adopt://通过
                //base64加密后
                String b64UrlEn1 = Base64.getUrlEncoder().encodeToString(mobileNumber.getBytes(StandardCharsets.UTF_8));
                String link = yunpianSmsClient.addShortUrl(url + b64UrlEn1);
                yunpianSmsClient.adoptSend(mobileNumber, link);
                break;
            case noadopt:
                //驳回
                String b64UrlEn = Base64.getUrlEncoder().encodeToString(mobileNumber.getBytes("utf-8"));
                String link1 = yunpianSmsClient.addShortUrl(url + b64UrlEn);
                yunpianSmsClient.noadoptSend(mobileNumber, link1);
                break;
            case refuse:
                //拒绝
                yunpianSmsClient.refuseSend(mobileNumber);
                break;
            case abolish:
                //废除
                break;
        }
    }

    /**
     * 生成短链接
     *
     * @param apikey   成功注册后登录云片官网,进入后台可查看
     * @param long_url 需要转换的长链接
     * @return json格式字符串
     */
    public static String shorten(String apikey, String long_url) throws YunpianException {
        Map<String, String> params = new HashMap<String, String>();
        params.put("apikey", apikey);
        params.put("long_url", long_url);
        return post("https://sms.yunpian.com/v2/short_url/shorten.json", params);
    }

    @Override
    public void export(AdminUser adminUser, DriverRegistrationInfoExportWrapper wrapper, HttpServletResponse response) throws IOException {
        AdminUserIdentityPresenter identity = (AdminUserIdentityPresenter) adminUser.getIdentity();
        switch (adminUser.getAccountType()) {
            case company:
                wrapper.setCompanyIds(identity.getCompanyIds());
                break;
            case canton:
                wrapper.setDriverRegionIds(identity.getDriverRegionIds());
                break;
        }
        List<DriverAuditPagePresenter> list =
                driverAuditInfoMapper.selectDriverRegistrationInfoList(wrapper);

        List<DriverRegistrationInfoExportPresenter> result = new ArrayList<>();

        if (ObjectUtil.isNotEmpty(list)) {
            List<Long> driverRegionIds = list.stream()
                    .map(DriverAuditPagePresenter::getDriverRegionId)
                    .collect(toList());
            List<Long> companyIds = list.stream()
                    .map(DriverAuditPagePresenter::getCompanyId)
                    .collect(toList());

            //驳回原因转换格式
            //运营区名称
            QueryWrapper<GeoDriverRegion> driverRegionQueryWrapper = new QueryWrapper<>();
            driverRegionQueryWrapper.select("id", "name");
            driverRegionQueryWrapper.in("id", driverRegionIds);
            List<Map<String, Object>> maps = geoDriverRegionMapper.selectMaps(driverRegionQueryWrapper);
            //公司名称
            QueryWrapper<Company> companyQueryWrapper = new QueryWrapper<>();
            companyQueryWrapper.select("id", "name");
            companyQueryWrapper.in("id", companyIds);
            List<Map<String, Object>> companyMaps = companyMapper.selectMaps(companyQueryWrapper);


            list.forEach(e -> {
                Long driverRegionId = e.getDriverRegionId();
                Long companyId = e.getCompanyId();
                //行政区信息
                maps.stream().filter(c -> c.get("id").equals(driverRegionId)).map(c -> String.valueOf(c.get("name"))).forEach(e::setDriverRegionName);
                //公司名称
                companyMaps.stream().filter(c -> c.get("id").equals(companyId)).map(c -> String.valueOf(c.get("name"))).forEach(e::setCompanyName);
            });

            result = BeanUtil.copyToList(list, DriverRegistrationInfoExportPresenter.class);
        }

        String fileName = URLEncoder.encode("司机自主注册导出", "UTF-8").replaceAll("\\+", "%20");
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
        EasyExcel.write(response.getOutputStream(), DriverRegistrationInfoExportPresenter.class)
                .sheet(0)
                .doWrite(result);
    }

    @Override
    public RestResult<Boolean> auditCertificate(AdminUser adminUser, Long id, DriverAuditCertificateWrapper req) {
        // 校验是否存在
        DriverAuditInfo item = driverAuditInfoMapper.selectById(id);
        if (ObjectUtil.isEmpty(item)) {
            return RestResult.build(ResultEnum.NOT_FOUND);
        }

        if (DriverAuditInfoType.register.equals(item.getType())) {
            return RestResult.failed("类型错误，只能审核证件更新信息");
        }

        if (!Arrays.asList(DriverRegistrationInfoSate.adopt, DriverRegistrationInfoSate.refuse).contains(req.getState())) {
            return RestResult.failed("审核结果，参数错误");
        }

        if (!DriverRegistrationInfoSate.under_review.equals(item.getState())) {
            return RestResult.failed("已经审核过了");
        }

        // 更新
        new LambdaUpdateChainWrapper<>(driverAuditInfoMapper)
                .eq(DriverAuditInfo::getId, id)
                .set(DriverAuditInfo::getState, req.getState())
                .set(DriverAuditInfo::getUpdatedAt, new Date())
                .update();

        // log
        DriverAuditLog auditLog = new DriverAuditLog();
        auditLog.setDriverAuditId(id);
        auditLog.setAdminId(adminUser.getId());
        auditLog.setState(req.getState());

        driverAuditLogic.saveLog(auditLog);

        // push
        DriverAuditSendMsgWrapper sendMsg = new DriverAuditSendMsgWrapper();
        sendMsg.setId(item.getDriverId());
        sendMsg.setUseGroup(DriverAuditSendMsgWrapper.useGroup.driver);

        String title;
        String content;
        if (DriverRegistrationInfoSate.adopt.equals(req.getState())) {
            title = "您的证件更新审核已通过";
            content = "祝您使用愉快";
        } else {
            title = "您的证件更新审核未通过";
            content = "请根据您更新后的证件重新上传";
        }
        sendMsg.setTitle(title);
        sendMsg.setContent(content);
        taxiService.sendPushMsg(sendMsg);

        if (DriverRegistrationInfoSate.adopt.equals(req.getState())) {
            // 审核通过，需更新 driverExtraInformation 表
            LambdaQueryWrapper<DriverExtraInformation> extraWrapper = new LambdaQueryWrapper<>();

            extraWrapper.eq(DriverExtraInformation::getDriverId, item.getDriverId());
            DriverExtraInformation extra = driverExtraInformationMapper.selectOne(extraWrapper);

            Boolean isVehicleLicence = DriverAuditInfoType.vehicleLicence.equals(item.getType());

            // 更新 正常
            Integer normal = change(extra.getNormalState(), 1, isVehicleLicence);

            // 更新 待更新
            Integer update = change(extra.getUpdateState(), 0, isVehicleLicence);

            // 更新 过期
            Integer overdue = change(extra.getOverdueState(), 0, isVehicleLicence);

            new LambdaUpdateChainWrapper<>(driverExtraInformationMapper)
                    .eq(DriverExtraInformation::getId, extra.getId())
                    .set(DriverExtraInformation::getNormalState, normal)
                    .set(DriverExtraInformation::getUpdateState, update)
                    .set(DriverExtraInformation::getOverdueState, overdue)
                    .set(Objects.nonNull(item.getVehicleLicenceExpiringTimestamp()), DriverExtraInformation::getVehicleLicenceExpiringTimestamp, item.getVehicleLicenceExpiringTimestamp())
                    .set(Objects.nonNull(item.getQualificationCertificateExpiringTimestamp()), DriverExtraInformation::getQualificationCertificateExpiringTimestamp, item.getQualificationCertificateExpiringTimestamp())
                    .set(DriverExtraInformation::getUpdatedAt, new Date())
                    .update();
        }

        return RestResult.success(true);
    }

    /**
     * @param currentTenByteState    当前十进制状态
     * @param updateCertificateState 行驶证/从业资格证将要变更的状态
     * @param isVehicleLicence       是否是行驶证变更
     * @return
     */
    public static Integer change(int currentTenByteState, int updateCertificateState, Boolean isVehicleLicence) {
        //当前状态由十进制转为二进制
        String currentState = "";
        switch (currentTenByteState) {
            case 0:
                currentState = "00";
                break;
            case 1:
                currentState = "01";
                break;
            case 2:
                currentState = "10";
                break;
            case 3:
                currentState = "11";
                break;
        }

        int index = 0;
        if (!isVehicleLicence) { //不是行驶证
            index = 1;
        }

        String str = String.valueOf(updateCertificateState);

        StringBuilder sb = new StringBuilder(currentState);
        sb.replace(index, index + 1, str);
        String returnTwoByteState = sb.toString();

        int returnTenByte = Integer.valueOf(returnTwoByteState, 2);
        return returnTenByte;
    }
}